home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 109 / EnigmaAmiga109CD.iso / dalla rivista / amiga.free / sorgenti vari / wolf3dmacsource.sit / Wolf3DMacSource / Doors.c < prev    next >
C/C++ Source or Header  |  1994-10-04  |  8KB  |  320 lines

  1. #include "Wolfdef.h"
  2. #include <string.h>
  3.  
  4. /**********************************
  5.  
  6.     Rules for door operation
  7.  
  8. door->position holds the amount the door is open, ranging from 0 to TILEGLOBAL-1
  9.  
  10. The number of doors is limited to 64 because various fields are only 6 bits
  11.  
  12. Open doors conect two areas, so sounds will travel between them and sight
  13.     will be checked when the player is in a connected area.
  14.  
  15. areaconnect has a list of connected area #'s, used to create the table areabyplayer
  16.  
  17. Every time a door opens or closes the areabyplayer matrix gets recalculated.
  18.     An area is True if it connects with the player's current spor.
  19.  
  20. **********************************/
  21.  
  22. /**********************************
  23.  
  24.     Insert a connection between two rooms
  25.     Note: I can have MORE than one connection between rooms
  26.     so it is VALID to have duplicate entries (1,6) & (1,6)
  27.     Each call to AddConnection must be balanced with a call to RemoveConnection
  28.         
  29. **********************************/
  30.  
  31. void AddConnection(Word Area1,Word Area2)
  32. {
  33.     connect_t *DestPtr;
  34.     
  35.     DestPtr = &areaconnect[ConnectCount];    /* Make pointer to the last record */
  36.     DestPtr->Area1 = Area1;                    /* Init the struct */
  37.     DestPtr->Area2 = Area2;
  38.     ++ConnectCount;                            /* Add 1 to the valid list */
  39. }
  40.  
  41. /**********************************
  42.  
  43.     Remove a connection between two rooms
  44.     Note: I can have MORE than one connection between rooms
  45.     so it is VALID to have duplicate entries (1,6) & (1,6)
  46.         
  47. **********************************/
  48.  
  49. void RemoveConnection(Word Area1,Word Area2)
  50. {
  51.     Word i;
  52.     connect_t *DestPtr;
  53.     
  54.     DestPtr = &areaconnect[0];        /* Init the scan pointer */
  55.     i = ConnectCount;                /* Init the count */
  56.     if (!i) {
  57.         return;
  58.     }
  59.     do {
  60.         if (DestPtr->Area1 == Area1 &&    /* Match? */
  61.             DestPtr->Area2 == Area2) {
  62.             --ConnectCount;            /* Remove the count */
  63.             DestPtr[0] = areaconnect[ConnectCount];    /* Copy last to current */
  64.             break;            /* I'm done! */
  65.         }
  66.         ++DestPtr;        /* Next entry to scan */
  67.     } while (--i);        /* Should NEVER fall out! */
  68. }
  69.  
  70. /**********************************
  71.  
  72.     Recursive routine to properly set the areabyplayer array by
  73.     using the contents of the areaconnect array.
  74.     Scans outward from playerarea, marking all connected areas.
  75.     
  76. **********************************/
  77.  
  78. void RecursiveConnect(Word areanumber)
  79. {
  80.     Word i;
  81.     Word j;
  82.     connect_t *AreaPtr;
  83.     
  84.     areabyplayer[areanumber] = TRUE;    /* Mark this spot (Prevent overflow) */
  85.  
  86.     i = ConnectCount;        /* Init index */
  87.     if (i) {                /* No doors available? */
  88.         AreaPtr = &areaconnect[0];    /* Get a local pointer */
  89.         do {
  90.             if (AreaPtr->Area1 == areanumber) {        /* Am I in this pair? */
  91.                 j = AreaPtr->Area2;            /* Follow this path */
  92.                 goto TryIt;
  93.             } 
  94.             if (AreaPtr->Area2 == areanumber) {        /* The other side? */
  95.                 j = AreaPtr->Area1;            /* Follow this side */
  96. TryIt:
  97.                 if (!areabyplayer[j]) {        /* Already been here? */
  98.                     RecursiveConnect(j);    /* Link it in... */    
  99.                 }
  100.             }
  101.             ++AreaPtr;                /* Next entry */
  102.         } while (--i);    /* All done? */
  103.     }
  104. }
  105.  
  106. /**********************************
  107.  
  108.     Properly set the areabyplayer record
  109.     
  110. **********************************/
  111.  
  112. void ConnectAreas(void)
  113. {
  114.     memset(areabyplayer,0,sizeof(areabyplayer));        /* Zap the memory */
  115.     RecursiveConnect(MapPtr->areasoundnum[actors[0].areanumber]);    /* Start here */
  116. }
  117.  
  118. /**********************************
  119.  
  120.     Start a door opening
  121.     
  122. **********************************/
  123.  
  124. void OpenDoor(door_t *door)
  125. {
  126.     if (door->action == DR_OPEN) {    /* Already open? */
  127.         door->ticcount = 0;            /* Reset open time (Keep open) */
  128.     } else {
  129.         door->action = DR_OPENING;    /* start it opening*/
  130.     }    /* The door will be made passable when it is totally open */
  131. }
  132.  
  133. /**********************************
  134.  
  135.     Start a door closing
  136.     
  137. **********************************/
  138.  
  139. void CloseDoor(door_t *door)
  140. {
  141.     Word tile,tilex,tiley;
  142.     Word *TilePtr;
  143.     int delta;
  144.  
  145. /* don't close on anything solid */
  146.  
  147.     tilex = door->tilex;        /* Get the current tile */
  148.     tiley = door->tiley;
  149.     TilePtr = &tilemap[tiley][tilex];    /* Get pointer to tile map */
  150.  
  151.     if (door->action != DR_OPENING) {    /* In the middle of opening? */
  152.     
  153. /* don't close on an actor or bonus item */
  154.  
  155.         tile = TilePtr[0];        /* What's the tile? */
  156.         if (tile & TI_BODY) {
  157.             door->action = DR_WEDGEDOPEN;    /* bodies never go away */
  158.             return;
  159.         }
  160.         if (tile & (TI_ACTOR | TI_GETABLE) ) {    /* Removable? */
  161.             door->ticcount = 60;        /* wait a while before trying to close again */
  162.             return;
  163.         }
  164.     
  165. /* Don't close on the player */
  166.  
  167.         delta = actors[0].x - ((tilex<<8)|0x80);
  168.         if (w_abs(delta) <= (0x82+PLAYERSIZE)) {
  169.             delta = actors[0].y - ((tiley<<8)|0x80);
  170.             if (w_abs(delta) <= (0x82+PLAYERSIZE)) {
  171.                 return;        /* It's touching the player! */
  172.             }
  173.         }
  174.     }
  175.     door->action = DR_CLOSING;    /* Close the door */
  176.     TilePtr[0] |= (TI_BLOCKMOVE|TI_BLOCKSIGHT);    /* make the door space a solid tile*/
  177. }
  178.  
  179. /**********************************
  180.  
  181.     Open or Close a door (Press space at a door)
  182.     
  183. **********************************/
  184.  
  185. void OperateDoor(Word dooron)
  186. {
  187.     Word type;
  188.     door_t *door;
  189.     
  190.     door = &doors[dooron];    /* Which door? */
  191.     type = door->info>>1;    /* Get the door type */
  192.     
  193.     if ( (type==1 && !(gamestate.keys&1)) || (type==2 && !(gamestate.keys&2)) ) {
  194.         PlaySound(SND_LOCKEDDOOR);        /* The door is locked */
  195.         return;    
  196.     }
  197.  
  198.     switch (door->action) {
  199.     case DR_CLOSED:
  200.     case DR_CLOSING:
  201.         OpenDoor(door);        /* Open the door */
  202.         break;
  203.     case DR_OPEN:
  204.     case DR_OPENING:        
  205.         CloseDoor(door);    /* Close the door */
  206.     }
  207. }
  208.  
  209. /**********************************
  210.  
  211.     Close the door after a few seconds
  212.     
  213. **********************************/
  214.  
  215. void DoorOpen(door_t *door)
  216. {
  217.     door->ticcount+=TicCount;        /* Inc the tic value */
  218.     if (door->ticcount >= OPENTICS) {    /* Time up? */
  219.         door->ticcount = OPENTICS-1;    /* So if the door can't close it will keep trying*/
  220.         CloseDoor(door);    /* Try to close the door */
  221.     }
  222. }
  223.  
  224. /**********************************
  225.  
  226.     Step the door animation for open, mark as DR_OPEN if all the way open
  227.     
  228. **********************************/
  229.  
  230. void DoorOpening(door_t *door)
  231. {
  232.     Word position;
  233.     Word area1,area2;
  234.     Byte *SoundNumPtr;
  235.     
  236.     position = door->position;    /* Get the pixel position */
  237.  
  238.     if (!position) {            /* Fully closed? */
  239.     
  240.     /* door is just starting to open, so connect the areas*/
  241.         SoundNumPtr = MapPtr->areasoundnum;
  242.         area1 = SoundNumPtr[door->area1];
  243.         area2 = SoundNumPtr[door->area2];
  244.         AddConnection(area1,area2);        /* Link the two together */
  245.         ConnectAreas();                    /* Link the map */
  246.         if (areabyplayer[area1] || areabyplayer[area2]) {    /* Can I hear it? */
  247.             PlaySound(SND_OPENDOOR);        /* Play the door sound */
  248.         }
  249.     }
  250.  
  251. /* slide the door open a bit */
  252.  
  253.     position += DOORSPEED*TicCount;        /* Move the door a bit */
  254.     if (position >= TILEGLOBAL-1) {    /* Fully open? */
  255.     
  256.     /* Door is all the way open */
  257.     
  258.         position = TILEGLOBAL-1;    /* Set to maximum */
  259.         door->ticcount = 0;            /* Reset the timer for closing */
  260.         door->action = DR_OPEN;        /* Mark as open */
  261.         tilemap[door->tiley][door->tilex] &= ~(TI_BLOCKMOVE|TI_BLOCKSIGHT);    /* Mark as enterable */
  262.     }
  263.     door->position = position;    /* Set the new position */
  264. }
  265.  
  266. /**********************************
  267.  
  268.     Step the door animation for close,
  269.     mark as DR_CLOSED if all the way closed
  270.     
  271. **********************************/
  272.  
  273. void DoorClosing(door_t *door)
  274. {
  275.     int position;
  276.     Byte *SoundNumPtr;
  277.  
  278.     position = door->position-(DOORSPEED*TicCount);    /* Close a little more */
  279.  
  280.     if (position <= 0) {        /* Will I close now? */
  281.     /* door is closed all the way, so disconnect the areas*/
  282.         SoundNumPtr = MapPtr->areasoundnum;    /* Unlink the sound areas */
  283.         RemoveConnection(SoundNumPtr[door->area1],SoundNumPtr[door->area2]);    
  284.         ConnectAreas();        /* Reset areabyplayer */
  285.         door->action = DR_CLOSED;    /* It's closed */
  286.         position = 0;    /* Mark as closed */
  287.     }
  288.     door->position = position;    /* Set the new position */
  289. }
  290.  
  291. /**********************************
  292.  
  293.     Process all the doors each game loop
  294.     
  295. **********************************/
  296.  
  297. void MoveDoors(void)
  298. {
  299.     Word dooron;        /* Which door am I on? */ 
  300.     door_t *door;        /* Pointer to current door */
  301.     
  302.     dooron = numdoors;    /* How many doors to scan? */
  303.     if (dooron) {        /* Any doors at all? */
  304.         door = doors;        /* Pointer to the first door */
  305.         do {
  306.             switch (door->action) {    /* Call the action code */
  307.             case DR_OPEN:
  308.                 DoorOpen(door);        /* Check to close the door */
  309.                 break;
  310.             case DR_OPENING:        /* Continue the door opening */
  311.                 DoorOpening(door);
  312.                 break;
  313.             case DR_CLOSING:        /* Close the door */
  314.                 DoorClosing(door);
  315.             }
  316.             ++door;            /* Next pointer */
  317.         } while (--dooron);    /* All doors done? */
  318.     }
  319. }
  320.